package cn.sjx.modules.nbiot.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.sjx.modules.nbiot.business.IBusinessServer;
import cn.sjx.modules.nbiot.business.impl.IotProtocolBusinessServerImpl_0x20;
import cn.sjx.modules.nbiot.business.impl.IotProtocolBusinessServerImpl_0x21;
import cn.sjx.modules.nbiot.entity.common.BusinessBean;
import cn.sjx.modules.nbiot.entity.common.IotProtocolConstants;
import cn.sjx.modules.nbiot.entity.receive.ReceiveBase;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.net.DatagramPacket;
import java.util.HashMap;
import java.util.Map;

/**
 * 响应数据发送 handler
 *
 * @Author: sjx
 * @Date: 2019年08月30日 0030 15:07:21
 */
@Component
public class SendServerAioHandler {

    private static final Log logger = LogFactory.get();

    /**
     * 业务实现方法类
     */
    public static Map<Integer, Class<? extends IBusinessServer>> businessMap = null;

    static {
        businessMap = new HashMap<Integer, Class<? extends IBusinessServer>>(2);
        /**
         * 收到：地磁状态发生变化，地磁检测器通过 NB-Iot 网络向占道平台发送数据报文。 地磁数据报文结构说明 (0x20)
         * 响应：地磁检测器和占道平台之间存在ACK机制，占道平台会分析地磁检测器的数据报文和心 跳报文信息，并返回对应的确认报文
         */
        businessMap.put(IotProtocolConstants.GEOMAGNETIC_RECEIVING_STATE, IotProtocolBusinessServerImpl_0x20.class);

        /**
         * 收到：如果需要心跳包，需联系相关销售人员提出要求，出厂前可进行配置，如果未配置有心跳包功能已出厂的设备，无法进行配置修改。地磁心跳包报文结构说明（0x21）
         * 响应：地磁检测器和占道平台之间存在ACK机制，占道平台会分析地磁检测器的数据报文和心 跳报文信息，并返回对应的确认报文
         */
        businessMap.put(IotProtocolConstants.GEOMAGNETIC_HEARTBEAT_PACKET, IotProtocolBusinessServerImpl_0x21.class);
    }

    @Async("taskExecutor")
    public void sendData(BusinessBean businessBean) {
        Map<String, Object> beanMap = null;
        try {
            // 获取接收报文与发送设备地址
            ReceiveBase receiveMsg = businessBean.getReceiveMsg();
            beanMap = BeanUtil.beanToMap(receiveMsg);

            // 获取接收报文的对应处理类
            int type = receiveMsg.getType();
            Class<? extends IBusinessServer> cls = businessMap.get(type);

            // 未找到实现方法则跳过此次执行
            if (null == cls) {
                return;
            }

            // 实例化业务处理类类
            IBusinessServer iBusinessServer = cls.newInstance();

            // 执行业务方法，并发送报文信息
            byte[] sendByteMsg = iBusinessServer.businessHandler(receiveMsg, businessBean.getByteMessage());

            // 打印日志

            logger.info("======> 【地磁（{}）|接收|解码】收到来自 {} 的请求：{}", MapUtil.getStr(beanMap, "magId"),
                    businessBean.getInetSocketAddress(), beanMap);
            logger.info("======> 【地磁（{}）|发送|报文】向 {} 发送处理结果：{}", MapUtil.getStr(beanMap, "magId"),
                    businessBean.getInetSocketAddress(), HexUtil.encodeHexStr(sendByteMsg, false));

            // 发送数据
            businessBean.getDatagramSocket().send(new DatagramPacket(sendByteMsg, sendByteMsg.length, businessBean.getInetSocketAddress()));
        } catch (Exception e) {
            logger.error("======> 【地磁（{}）|发送|数据处理失败】向{}发送处理结果", MapUtil.getStr(beanMap, "magId"),
                    businessBean.getInetSocketAddress());
            e.printStackTrace();
        }
    }

}
